#include "StdAfx.h"
#include "Scene.h"

Scene::Scene()
{
	this->aN = 0;
	this->lN = 0;
	this->aMax = 10;
	this->lMax = 16;
	this->Actions = gcnew array<Action ^>(aMax);
	this->Links = gcnew array<Link ^>(lMax);
	this->res = gcnew ImgResource();
}
void Scene::Preload(System::Windows::Forms::ContextMenuStrip^ mRB)
{
	for (int i=0;i<this->aMax;i++) {this->Actions[i] = gcnew Action(this->res,-1,mRB);}
	for (int i=0;i<this->lMax;i++) {this->Links[i] = gcnew Link(this->res,-1,mRB,0,0,this->Actions[0],this->Actions[0],1,1,1,1);}
}
void Scene::CreateAction(int x,int y)
{
	CreateObject(x,y,0);
}
void Scene::CreateStart(int x,int y)
{
	CreateObject(x,y,1);
}
void Scene::CreateEnd(int x,int y)
{
	CreateObject(x,y,2);
}
void Scene::CreateComment(int x,int y)
{
	CreateObject(x,y,7);
}
void Scene::CreateSignal(int x,int y)
{
	CreateObject(x,y,3);
}
void Scene::CreateSignalRecv(int x,int y)
{
	CreateObject(x,y,4);
}
void Scene::CreateMultiplexerVert(int x,int y)
{
	CreateObject(x,y,5);
}
void Scene::CreateMultiplexerHort(int x,int y)
{
	CreateObject(x,y,6);
}
void Scene::CreateObject(int x, int y, int type)
{
	if (FindFreeA() != (-1))
	{
		Actions[FindFreeA()]->set(this->res,type,x,y);
		paint();
		this->aN++;
	}
}
int Scene::FindFreeA()
{
	for (int i=0;i<this->aMax;i++) if (this->Actions[i]->get('t') == -1){return i;};
	return -1;
}
int Scene::FindFreeL()
{
	for (int i=0;i<this->lMax;i++) if (this->Links[i]->get('t') == -1){return i;};
	return -1;
}
int Scene::getAMax()
{
	return this->aMax;
}
int Scene::getLMax()
{
	return this->lMax;
}
void Scene::paint()
{
	for (int i=0;i<this->aMax;i++) {this->Actions[i]->paint();}
	for (int i=0;i<this->lMax;i++) {this->Links[i]->paint(this->res,this->getFromNum(this->Links[i]),this->getToNum(this->Links[i]),this->getFromMax(this->Links[i]),this->getToMax(this->Links[i]));}
}
int Scene::isAction(System::Object^  object)
{
	System::String^ a = object->GetType()->FullName;
	System::String^ P = gcnew System::String("System.Windows.Forms.PictureBox");
	System::String^ L = gcnew System::String("System.Windows.Forms.Label");
	for (int i=0;i<this->aMax;i++)
	{
		if (a == P)
		{
			if ( (this->Actions[i]->getActionImg() == ((System::Windows::Forms::PictureBox^)object)))
			{
				return i;
			}
		}
		else if (a == L)
		{
			if ( (this->Actions[i]->getLabel() == ((System::Windows::Forms::Label^)object)) )
			{
				return i;
			}
		}
		else
		{
			return -2;
		}
	}
	return -1;
}
int Scene::isLink(System::Object^  object)
{
	System::String^ a = object->GetType()->FullName;
	System::String^ P = gcnew System::String("System.Windows.Forms.PictureBox");
	System::String^ L = gcnew System::String("System.Windows.Forms.Label");
	if (a == P)
	{
		for (int i=0;i<this->lMax;i++)
		{
			if ( (this->Links[i]->getSr() == ((System::Windows::Forms::PictureBox^)object)) || (this->Links[i]->getArrow() == ((System::Windows::Forms::PictureBox^)object)) || (this->Links[i]->getHort() == ((System::Windows::Forms::PictureBox^)object)) || (this->Links[i]->getVert() == ((System::Windows::Forms::PictureBox^)object)) )
			{
				return i;
			}
		}
	}
	return -1;
}
void Scene::DeleteObject(int n)
{
	for (int i=0;i<this->lMax;i++)
	{
		if ( this->Links[i]->get('t') != -1 )
		{
			//int t1=isAction((System::Object^)this->Links[i]->link_from->getActionImg());
			//int t2=isAction((System::Object^)this->Links[i]->link_to->getActionImg());
			if ( (isAction((System::Object^)this->Links[i]->link_from->getActionImg()) == n) || (isAction((System::Object^)this->Links[i]->link_to->getActionImg()) == n))
			{
				DeleteLink(i);
			}
		}
	}
	this->Actions[n]->null();
	this->aN--;
}
void Scene::DeleteLink(int n)
{
	this->Links[n]->null();
	this->aN--;
}
void Scene::CreateLink(int n1,int n2,int type)
{
	if (FindFreeL() != (-1))
	{
		int fromN=1,toN=1,fromAM=2,toAN=2;
		Links[FindFreeL()]->set(this->res,type,1,1,this->Actions[n1],this->Actions[n2],fromN,toN,fromAM,toAN);
		paint();
		this->lN++;
	}
}
void Scene::SaveFile(System::String^ path)
{
	 FILE *stream;
	 if( (stream  = fopen( convertString(path), "w" )) != NULL ) 
	 {
		 fprintf(stream,"%d\n",this->aMax);
		 for (int i=0;i<this->aMax;i++)
		 {
			 fprintf(stream,"%d %d %d %d %d %s\n",this->Actions[i]->get('x')
												,this->Actions[i]->get('y')
												,this->Actions[i]->get('w')
												,this->Actions[i]->get('h')
												,this->Actions[i]->get('t')
												,convertString(this->Actions[i]->getLabel()->Text));
		 }
		 fprintf(stream,"%d\n",this->lMax);
		 for (int i=0;i<this->lMax;i++)
		 {
			 fprintf(stream,"%d %d %d %d %d\n",isAction((System::Object^)this->Links[i]->link_from->getActionImg())
												,isAction((System::Object^)this->Links[i]->link_to->getActionImg())
												,this->Links[i]->get('f')
												,this->Links[i]->get('p')
												,this->Links[i]->get('t'));
		 }
		 fclose(stream);
	 }
}
void Scene::OpenFile(System::String^ path)
{
	 FILE *stream;
	 if( (stream = fopen( convertString(path), "r" )) != NULL ) 
	 {
		 int x=0,y=0,t=0,sx=0,sy=0,aM=0,lM=0,to=0,from=0,f=0,p=0;
		 char buff[100];
		 //===============================================
		 fscanf(stream,"%d\n",&aM);
		 for (int i=0;i<aM;i++)
		 {
			fscanf(stream,"%d %d %d %d %d %s",&x,&y,&sx,&sy,&t,buff);
			this->Actions[i]->set(this->res,t,x,y);
			this->Actions[i]->getActionImg()->Size = System::Drawing::Size(sx,sy);
			this->Actions[i]->getLabel()->Text = gcnew System::String(buff);
		 }
		 //===============================================
		 fscanf(stream,"%d\n",&lM);
		 for (int i=0;i<aM;i++)
		 {
			fscanf(stream,"%d %d %d %d %d",&from,&to,&f,&p,&t);
			this->Links[i]->set(this->res,t,f,p,this->Actions[from],this->Actions[to],1,1,2,2);
		 }
	 }
	 fclose(stream);
}
char* Scene::convertString(System::String^ other)
{
	// Pin memory so GC can't move it while native function is called
	pin_ptr<const wchar_t> wch = PtrToStringChars(other);

	// Conversion to char* :
	// Can just convert wchar_t* to char* using one of the 
	// conversion functions such as: 
	// WideCharToMultiByte()
	// wcstombs_s()
	// ... etc
	size_t convertedChars = 0;
	size_t sizeInBytes = ((other->Length + 1) * 2);
	errno_t err = 0;
	char *ch = (char *)malloc(sizeInBytes);

	err = wcstombs_s(&convertedChars, ch, sizeInBytes, wch, sizeInBytes);
	return ch;
}
Scene^ Scene::MakeEqual(Scene^ other)
{
	this->aN = other->aN;
	this->lN = other->lN;
	for (int i=0;i<this->aMax;i++) {this->Actions[i]->MakeEqual(other->Actions[i]);}
	for (int i=0;i<this->lMax;i++) {this->Links[i]->MakeEqual(other->Links[i]
																,this->Actions[other->isAction((System::Object^)other->Links[i]->link_from->getActionImg())]
																,this->Actions[other->isAction((System::Object^)other->Links[i]->link_to->getActionImg())]);}
	this->paint();
	return this;
}

int Scene::getFromNum(Link^ link)
{
	int n=0;
	for (int i=0;i<this->lMax;i++) 
	{
		if ((this->Links[i]->link_from == link->link_from) && (this->Links[i]->link_from->get('t') != -1) && (this->Links[i]->get('t') != -1))
		{
			n++;
			if (this->Links[i] == link)
			{
				return n;
			}
		}
	}
	return 0;
}
int Scene::getToNum(Link^ link)
{
	int n=0;
	for (int i=0;i<this->lMax;i++) 
	{
		if ((this->Links[i]->link_to == link->link_to) && (this->Links[i]->link_to->get('t') != -1) && (this->Links[i]->get('t') != -1))
		{
			n++;
			if (this->Links[i] == link)
			{
				return n;
			}
		}
	}
	return 0;
}
int Scene::getFromMax(Link^ link)
{
	int n=0;
	for (int i=0;i<this->lMax;i++) 
	{
		if ((this->Links[i]->link_from == link->link_from) && (this->Links[i]->link_from->get('t') != -1) && (this->Links[i]->get('t') != -1))
		{
			n++;
		}
	}
	return n+1;
}
int Scene::getToMax(Link^ link)
{
	int n=0;
	for (int i=0;i<this->lMax;i++) 
	{
		if ((this->Links[i]->link_to == link->link_to) && (this->Links[i]->link_to->get('t') != -1) && (this->Links[i]->get('t') != -1))
		{
			n++;
		}
	}
	return n+1;
}